﻿using System.Linq;
using Validate.Net.Core;

namespace Validate.Net.Internals.Globalization.zh_CN
{
    /// <summary>
    /// 属性只能是中国大陆统一社会信用代码
    /// <para>USCI, Unified Social Credit Identifier</para>
    /// </summary>
    public sealed class USCIAttribute : ValidateBaseAttribute
    {
        /// <summary>
        /// 属性只能是中国大陆统一社会信用代码
        /// </summary>
        /// <param name="internalPrompts">内联提示语。优先级最高
        /// <list type="bullet">
        /// <item>提示语只描述校验失败的原因，而不应该包含其他内容。（ 例如 : 不能是默认值、必须填写 等等类似的语句 )</item>
        /// <item>内联提示语将覆盖所有其他设置</item>
        /// <item>提示语优先级: <see cref="ValidateBaseAttribute.InternalPrompts"/> > <see cref="CustomPrompts.Set{T}(string)"/> > <see cref="ValidateBaseAttribute.Prompts"/></item>
        /// </list>
        /// </param>
        public USCIAttribute(string internalPrompts = null) : base(internalPrompts)
        {

        }

        public override string Prompts => Properties.Resources.cnzh_USCIPrompts;

        public override bool OnCheck(object value)
        {
            if (value is string str)
            {
                return IsSocialCreditCode(str);
            }
            else
            { return false; }
        }

        /// <summary>
        /// 验证规则
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        static bool IsSocialCreditCode(string code)
        {
            if (code.Length != 18) return false;
            code = code.ToUpper();
            int[] factor = { 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28 };
            string str = "0123456789ABCDEFGHJKLMNPQRTUWXY";
            int total = factor.Select((p, i) => p * str.IndexOf(code[i])).Sum();
            int index = total % 31 == 0 ? 0 : (31 - total % 31);
            return str[index] == code.Last();
        }
    }
}
